今天來介紹通訊協定WebSocket吧,最近都會想主題想一陣子才知道要寫什麼,各種前輩的文章翻來翻去,好就介紹這個吧ˊˇˋ
先看一下wiki介紹
WebSocket是一種網路傳輸協定,可在單個TCP連接上進行全雙工通訊,位於OSI模型的應用層。
WebSocket使得客戶端和伺服器之間的資料交換變得更加簡單,允許伺服器端主動向客戶端推播資料。在WebSocket中,只需要完成一次交握,兩者之間就可以建立永續性的連接,並進行雙向資料傳輸。
在http中,client請求server回應,連線就會中斷了,若是server有更新要傳回,也只能等client發出請求才能回應。若是傳輸頻率很高,就必須讓client不斷發出請求,在效能上的表現並不好,也不能真正取得即時訊息。
而能夠即時通訊的WebSocket協定就在2008年因應而生。
WebSocket是雙向通訊模式,在client送出handshake(握手)建立連線後,即開始雙向模式互動,client與server端都能隨時將資料傳給對方,直到disconnect為止。
我們比較一下WebSocket與http兩種協定有什麼相似之處與相異之處
TCP的一種傳輸協定OSI Layer7協定Http為單向通訊協議;Websocket是雙向通訊。Http為client向server發起連線;WebSocket以Handshake建立連線。Http為短連線,請求結束後會釋放連線;WebSocket建立連線後伺服器會持續監聽請求,不用每次重新連線。Go語言標準套件裡面沒有提供對WebSocket的支援,這邊使用由Gorilla團隊製作的WebSocket套件,gorilla/websocket。
go get github.com/gorilla/websocket
import(
"github.com/gorilla/websocket"
)
package main
import (
"log"
"net/http"
"fmt"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{}
func socketHandler(w http.ResponseWriter, r *http.Request) {
// Upgrade our raw HTTP connection to a websocket based one
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Print("Error during connection upgradation:", err)
return
}
defer func() {
log.Println("disconnect !!")
conn.Close()
}()
// The event loop
for {
messageType, message, err := conn.ReadMessage()
if err != nil {
log.Println("Error during message reading:", err)
break
}
log.Printf("Received: %s", message)
err = conn.WriteMessage(messageType, message)
if err != nil {
log.Println("Error during message writing:", err)
break
}
}
}
func home(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Index Page")
}
func main() {
http.HandleFunc("/socket", socketHandler)
log.Println("server start at :8080")
http.HandleFunc("/", home)
log.Fatal(http.ListenAndServe(":8080", nil))
}
寫完後可以將伺服器執行起來
這邊客戶端的功能是每隔一秒會往伺服器傳一次"WebSocket Success!"
package main
import (
"log"
"time"
"github.com/gorilla/websocket"
)
func main() {
conn, _, err := websocket.DefaultDialer.Dial("ws://127.0.0.1:8080/socket", nil)
if err != nil {
log.Fatal("dial:", err)
}
defer conn.Close()
for {
time.Sleep(time.Second)
err = conn.WriteMessage(websocket.TextMessage, []byte("WebSocket Success!"))
if err != nil {
log.Println(err)
return
}
_, msg, err := conn.ReadMessage()
if err != nil {
log.Println("read:", err)
return
}
log.Printf("receive: %s\n", msg)
}
}
客戶端這邊顯示
output:
2022/10/08 15:54:04 receive: WebSocket Success!
2022/10/08 15:54:05 receive: WebSocket Success!
.
.
.
伺服器端顯示
output:
2022/10/08 15:54:04 Received: WebSocket Success!
2022/10/08 15:54:05 Received: WebSocket Success!
.
.
.
一份WebSocket測試完成了,這邊是最基礎的使用法
慢聊Go之GoLang中使用Gorilla Websocket|Go主题月
https://juejin.cn/post/6946952376825675812
Golang 如何建構一個 websocket server
https://ithelp.ithome.com.tw/articles/10208531
WebSocket
https://ithelp.ithome.com.tw/articles/10249282
WebSocket協議入門介紹
https://iter01.com/420761.html